/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is iRecipe code.
 *
 * The Initial Developer of the Original Code is Robert Morris.
 * Portions created by the Initial Developer are Copyright (C) 2006
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

package com.pavisoft.irecipe;

import java.util.ArrayList;
import org.jdom.Element;

/**
 * @author Robert Morris
 *
 * Holds all information needed for recipe, including name, ingredients,
 * and instructions.
 *
 */
public class Recipe
{
    private String name;
    private String description;
    private String preptime;
    private String yield;
    private ArrayList<Ingredient> ingredients;
    private String directions;
    private ArrayList<String> keywords;
    
    /** Creates a new <code>Recipe</code> with a blank name, etc. and no
     *  ingredients. */
    public Recipe()
    {
        this("", new ArrayList<Ingredient>(), "");
    }
    /** Creates a new instance of Recipe with specified name, ingredients, and directions */
    public Recipe(String name, ArrayList<Ingredient> ingredients, String directions)
    {
        this.setName(name);
        this.ingredients = ingredients;
        this.setDirections(directions);
        this.keywords = new ArrayList<String>();
    }

    public String getName()
    {
        return name;
    }

    public synchronized void setName(String name)
    {
        this.name = name;
    }

    public ArrayList<Ingredient> getIngredients()
    {
        return ingredients;
    }
    
    public Ingredient getIngredient(int index)
    {
        return ingredients.get(index);
    }

    public synchronized void setIngredients(ArrayList<Ingredient> ingredients)
    {
        this.ingredients = ingredients;
    }
    
    public synchronized void addIngredient(Ingredient ingredient)
    {
        this.ingredients.add(ingredient);
    }
    
    /** Adds <code>ingredient</code> at position <code>at</code>. If <code>at</code>
     *  is greater than the size of the ingredients list, <code>ingredient</code>
     *  will simply be added to the end of the ingredients list. */
    public synchronized void addIngredient(Ingredient ingredient, int at)
    {
        try
        {          
            this.ingredients.add(at, ingredient);
        }
        catch (IndexOutOfBoundsException ex)
        {
            this.addIngredient(ingredient);
        }
    }
    
    public synchronized void removeIngredient(int index)
    {
        this.ingredients.remove(index);
    }
    
    public synchronized void setIngredient(int ingredientIndex, Ingredient newIngredient)
    {
        this.ingredients.set(ingredientIndex, newIngredient);
    }
    
    /** Moves the ingredient at <code>fromIndex</code> to <code>toIndex</code>.
     *  (Convienent for drag-and-drop GUIs.)
     *  @param fromIndex The index of the ingredient to move
     *  @param toIndex The index to which to move the ingredient. (Note that this
     *   paramater reflects the index before modification of the ingredients list,
     *   so the resulting index may actually be different.)
     */
    public synchronized void moveIngredient(int fromIndex, int toIndex)
    {
        if (fromIndex == toIndex) return;
        
        this.ingredients.add(toIndex, this.ingredients.get(fromIndex));
        
        if (fromIndex > toIndex)
        {
            this.ingredients.remove(fromIndex + 1);
        }
        else
        {
            this.ingredients.remove(fromIndex);
        }
    }
    
    public int getNumberOfIngredients()
    {
        return this.ingredients.size();
    }

    public String getDirections()
    {
        return directions;
    }

    public synchronized void setDirections(String directions)
    {
        this.directions = directions;
    }
    
    public Element toXML()
    {
        Element recipe = new Element("recipe");        
        Element head = new Element("head");
        Element desc = new Element("description");
        Element title = new Element("title");
        Element kwds = new Element("keywords");
        Element ingredients = new Element("ingredients");        
        Element directions = new Element("directions");
        
        title.addContent(this.name);
        
        head.addContent(title);
        if (this.description != null)
        {
           
            desc.addContent(this.description);
            head.addContent(desc);
        }
        
        if (this.keywords.size() > 0)
        {
            for (String s : keywords)
            {
                Element k = new Element("keyword");
                k.addContent(s);
                kwds.addContent(k);
            }
            head.addContent(kwds);
        }
        
        if (this.yield != null)
        {
            Element y = new Element("yield");
            y.addContent(this.yield);
            head.addContent(y);
        }
        
        if (this.preptime != null)
        {
            Element y = new Element("preptime");
            y.addContent(this.preptime);
            head.addContent(y);
        }
        
        recipe.addContent(head);
        
        for (Ingredient ing : this.getIngredients())
        {
            ingredients.addContent(ing.toXML());
        }
        
        recipe.addContent(ingredients);
        
        directions.addContent(this.getDirections());
        
        recipe.addContent(directions);
        
        return recipe;
    }

    public String getDescription()
    {
        return description;
    }

    public synchronized void setDescription(String description)
    {
        this.description = description;
    }
    
    /** Returns whether or not this recipe has the given keyword associated
      * with it (e.g., "vegetarian").
     */
    public boolean hasKeyword(String keyword)
    {
       boolean found = false;
       for (String s : this.keywords)
       {
           if (s.equals(keyword))
               found = true;
       }
       return found;
    }
    
    /** Returns string array containing all keywords associated with this recipe. */
    public String[] getKeywords()
    {
        return this.keywords.toArray(new String[keywords.size()]);
    }
    
    /** Adds <code>keyword</code> to the list of keywords associated with
     *  this recipe. */
    public void addKeyword(String keyword)
    {
        keywords.add(keyword);
    }
    
    /** Removes <code>keyword</code> from the list of keywords associated
     *  with this recipe. */
    public void removeKeyword(String keyword)
    {
        keywords.remove(keyword);
    }

    /** Returns preparation time, if specified, for this recipe.
     *  @return Preparation time if specified, or <code>null</code> if not.
     */
    public String getPrepTime()
    {
        return preptime;
    }
    
    /** Sets the preparation time for this recipe to the given value. */
    public void setPrepTime(String prepTime)
    {
        this.preptime = prepTime;
    }
    
    /** Returns yield of this recipe, if specified.
     *  @return Yield if specified, otherwise <code>null</code>. */
    public String getYield()
    {
        return yield;
    }

    /** Sets yield of this recipe to given value. */
    public void setYield(String yield)
    {
        this.yield = yield;
    }
    
}
